/**************************************** 
* IteradorLista.h
* Declaraci�n de la Clase IteradorLista
****************************************/

#ifndef __ITERADORLISTA_H__
#define __ITERADORLISTA_H__
#include "NodoLista.h"
#include "ErrorIteracionException.h"



// Forward declaration de Lista<T> para poder utilizarla:
template <class T> class Lista;


template <class T>
class IteradorLista {


	

	private:
		Lista<T>* lista;
		NodoLista<T>* actual;
		
		NodoLista<T>* getAnterior(){
		/* pre: La lista no est� vac�a (existe un nodo actual) y el nodo actual
		*		no es el primero.
		* post: -
		* Devuelve el nodo anterior al actual.
		*/
			NodoLista<T>* auxiliar = this->lista->getPrimero();

				while (auxiliar->tieneSiguiente()){
			
					NodoLista<T>* siguiente=auxiliar->getSiguiente();
					if (siguiente==actual) return auxiliar;
					else auxiliar=auxiliar->getSiguiente();

				}

				//Si no entr� en el ciclo while, el nodo en realidad no tiene un predecesor
				//y se debe lanzar una exepci�n.
				throw ErrorIteracionException("Se pidi� un nodo anterior al primero");
	
		}





	public:
		
		
		IteradorLista(Lista<T>* lista){
/* pre: -
 * post: Iterador creado y apuntando al
 *		 primer elemento de lista o al nulo si �sta est� vac�a.
*/
	this->lista=lista;
	if (lista->estaVacia()) this->actual=NULL;
	else this->actual=lista->getPrimero();
}


bool tieneSiguiente(){
/* pre: La lista no est� vacia (tiene un nodo actual)
 * post: -
 * Indica si el nodo actual est� enlazado a un siguiente nodo.
*/
	if((this->actual)!=NULL) return true;
	else return false;
}


T* siguiente(){
/* pre: Existe un nodo siguiente. Existe un nodo actual.
 * post: Devuelve el siguiente nodo y lo establece como nodo actual.
*/
	if (this->tieneSiguiente()){
		T* retorno = actual->getDato();
		actual = actual->getSiguiente();	
		return retorno;
	}
	else throw ErrorIteracionException("Se pidi� el nodo siguiente del �ltimo nodo.");
	//else throw ErrorIteracionException("Se pidi� un dato de un nodo inexistente");
}


T* getActual(){
/* pre: -
 * post: -
 * Devuelve el nodo actual
*/
	if ((this->actual)!=NULL)
		return this->actual->getDato();
	else throw ErrorIteracionException("Se pidi� un dato de un nodo inexistente");
}

void seek(unsigned int pos){
	//Posiciona de modo tal que el nodo actual sea el de la posición pos.
	//Convención: el primer nodo está en la posición 0.
	if (!lista->estaVacia()){
		int i=0;
		this->actual=lista->getPrimero();
		while (i<pos){
			if (actual->tieneSiguiente()){
				this->actual = actual->getSiguiente();
				i++;
			}
			else throw ErrorIteracionException("Se intento realizar un seek a una posicion mayor que el tamaño de una lista.");
		}
	}
	else throw ErrorIteracionException("Se intento realizar un seek en una lista vacia.");
}


void comienzo(){
/* pre: -
 * post: Iterador posicionado en el primer elemento de la lista.
*/
	if (!lista->estaVacia()) actual=lista->getPrimero();
	else actual=NULL;
}

virtual ~IteradorLista(){
/* pre: -
 * post: Libera los recursos asociados al iterador.
*/
}

};

#endif
